package socket;

import com.sun.org.apache.bcel.internal.generic.InstructionConstants;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
 * 聊天室客户端
 */
public class Client {
    /*
    java.net,Socket套接字
    Socket封装TCP协议的通讯细节,使得我们使用它来完成与远端计算机的链接,并基于
    两个流(一个输入流和一个输出流)的读写完成与远端计算机的数据交换
     */
    private Socket socket;
    /**
     * 构造方法,用于初始化客户端
     */
    public  Client(){
        try {
            /*
            实例化Socket时需要传入两个参数用于与服务端建立连接
            参数1:服务器计算机的IP地址,如果;链接本机可以用"localhost"代替
            参数2:服务端程序在服务端计算机开启的端口
                 通过该端口找到服务端计算机上的服务端程序
                 注:实例化Socket的过程就是连接过程,与服务端建立连接则实例化成功,
                 否则会抛出异常
             */
            System.out.println("正在连接服务端...");
            socket=new Socket("176.100.7.76exit" ,8088);
            System.out.println("与服务端建立连接!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 客户端开始工作的方法
     */
    public void start(){
        try {
            //启动读取服务端消息的线程
            ServerHandler handler=new ServerHandler();
            Thread t=new Thread(handler);
            t.start();

            /*
            Socket提供的方法:
            OutputStream getOutputStream()
            通过该方法获取一个字节输出流,使用该流写出的数据都会发送给远端计算机
             */
            OutputStream out=socket.getOutputStream();
            OutputStreamWriter osw=new OutputStreamWriter(out,"UTF-8");
            BufferedWriter bw=new BufferedWriter(osw);
            PrintWriter pw=new PrintWriter(bw,true);

            Scanner scan=new Scanner(System.in);
            System.out.println("开始聊天,单独输入exit退出");
            while (true){
                String line=scan.nextLine();
                if ("exit".equals(line)){
                    break;
                }
                pw.println(line);
            }

        } catch (IOException e) {
        }finally {
            //最终和服务端断开连接
            try {
                /*
                Socket的close调用后,通过socket获取的输入流与输出流的自动关闭了
                与此同时也会给远端计算机发送断开信号(TCP协议底层需要).否则远端
                计算机可能抛出异常:
                java.net.SocketException:Connection reset
                 */
                socket.close();
            } catch (IOException e) {
            }
        }

    }
    public static void main(String[] args){
        Client client=new Client();
        client.start();
    }
    /*
    该线程任务负责循环读取客户端发送过来的消息
     */
    private class ServerHandler implements  Runnable{
        public void run(){
            //通过socket获取输入流用来读取服务端法送过来的消息
            try {
                InputStream in=socket.getInputStream();
                InputStreamReader ins=new InputStreamReader(in,"UTF-8");
                BufferedReader br=new BufferedReader(ins);
                //循环读取服务端发送过来的每一行消息并输出到控制台
                String message;
                while ((message=br.readLine())!=null){
                    System.out.println(message);
                }
            } catch (IOException e) {
            }
        }
    }
}
